package com.sleepless.my.utils;

import io.jsonwebtoken.security.Jwks;
import io.netty.handler.codec.EncoderException;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.Encoder;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
import java.util.HashMap;

@Data
@Slf4j
@Component
public class FileUtil {
    @Value("${file.videoPath}")
    private String videoPath;

    @Value("${file.coverPath}")
    private String coverPath;

    @Value("${file.avatarPath")
    private String avatarPath;

    @Value("${file.imagePath")
    private String imagePath;

    @Value("${file.audioPath")
    private String audioPath;

    @Value("${file.basePath}")
    private String basePath;

    private HashMap<FileType, String> fileMap = new HashMap<>();
    @PostConstruct
    public void init() {
        fileMap.put(FileType.VIDEO, videoPath);
        fileMap.put(FileType.AVATAR, avatarPath);
        fileMap.put(FileType.IMAGE, imagePath);
        fileMap.put(FileType.AUDIO, audioPath);
        fileMap.put(FileType.COVER, coverPath);
    }
    public String saveFile(MultipartFile file,FileType type) {
        try {
            String fileName = file.getOriginalFilename()+"-"+getMd5(file);
            String fullPath=getFullPath(type,fileName);
            File dest = new File(fullPath);
            file.transferTo(dest);
            return fileName;
        } catch (IOException e) {
            throw new RuntimeException("Failed to save file", e);
        }
    }
    public String getMd5(MultipartFile file) {
        try {
            //获取文件的byte信息
            byte[] uploadBytes = file.getBytes();
            // 拿到一个MD5转换器
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] digest = md5.digest(uploadBytes);
            //转换为16进制
            return new BigInteger(1, digest).toString(16);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }
    public String getFullPath(FileType type,String fileName) {
        String prePath=basePath+ fileMap.get(type);
        File dir = new File(prePath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        return prePath+"/"+fileName;
    }

    // ffmpeg 获取本地视频信息
    public MultimediaInfo getMultimediaInfo(String localPath) {
        MultimediaInfo multimediaInfo = null;
        try {
            multimediaInfo = new MultimediaObject(new File(localPath)).getInfo();
        } catch (EncoderException | ws.schild.jave.EncoderException e) {
            System.out.println("获取多媒体文件信息异常");
            e.printStackTrace();
        }
        return multimediaInfo;
    }
    // 从url获取视频信息
    public MultimediaInfo getMultimediaInfoFromUrl(String url) {
        MultimediaInfo multimediaInfo = null;
        try {
            multimediaInfo = new MultimediaObject(new URL(url)).getInfo();
        } catch (Exception e) {
            System.out.println("获取多媒体文件信息异常");
            e.printStackTrace();
        }
        return multimediaInfo;
    }
    // 转换成wav
    public boolean formatAudioWav(String url) {
        File target = new File(coverPath);
        MultimediaObject multimediaObject;
        try {
            // 若是本地文件： multimediaObject = new MultimediaObject(new File("你的本地路径"));
            multimediaObject = new MultimediaObject(new URL(url));
            // 音频参数
            AudioAttributes audio = new AudioAttributes();
            // 采样率
            audio.setSamplingRate(SAMPLING_RATE);
            // 单声道
            audio.setChannels(SINGLE_CHANNEL);
            Encoder encoder = new Encoder();
            EncodingAttributes attrs = new EncodingAttributes();
            // 输出格式
            attrs.setOutputFormat("wav");
            attrs.setAudioAttributes(audio);
            encoder.encode(multimediaObject, target, attrs);
            return true;
        } catch (Exception e) {
            System.out.println("格式化音频异常");
            return false;
        }
    }
    // 转换成mp4
    public boolean formatVideoMp4(String url) {
        File target = new File(coverPath);//
        MultimediaObject multimediaObject;
        try {
            // 若是本地文件： multimediaObject = new MultimediaObject(new File("你的本地路径"));
            multimediaObject = new MultimediaObject(new URL(url));
            EncodingAttributes attributes = new EncodingAttributes();
            // 设置视频的音频参数
            AudioAttributes audioAttributes = new AudioAttributes();
            attributes.setAudioAttributes(audioAttributes);
            // 设置视频的视频参数
            VideoAttributes videoAttributes = new VideoAttributes();
            // 设置帧率
            videoAttributes.setFrameRate(25);
            attributes.setVideoAttributes(videoAttributes);
            // 设置输出格式
            attributes.setOutputFormat("mp4");
            Encoder encoder = new Encoder();
            encoder.encode(multimediaObject, target, attributes);
            return true;
        } catch (Exception e) {
            System.out.println("格式化视频异常");
            e.printStackTrace();
            return false;
        }
    }
    // 创建封面 传入视频的名字，返回封面的名字
    public String createThumbnail(String videoName) {
        String localVideoPath=getFullPath(FileType.VIDEO,videoName);
        String thumbnailName = System.currentTimeMillis()+".jpg";
        try {
            String fullPath=getFullPath(FileType.COVER,thumbnailName);
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localVideoPath);
            ffmpeg.addArgument("-ss");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument("0");
            ffmpeg.addArgument(fullPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("获取视频缩略图失败");
            e.printStackTrace();
            return null;
        }
        return thumbnailName ;
    }
    private static void blockFfmpeg(BufferedReader br) throws IOException {
        String line;
        // 该方法阻塞线程，直至合成成功
        while ((line = br.readLine()) != null) {
            doNothing(line);
        }
    }
    private static void doNothing(String line) {
        System.out.println(line);
    }
    private static final int SAMPLING_RATE = 16000;
    private static final int SINGLE_CHANNEL = 1;
    public enum FileType{
        VIDEO,
        IMAGE,
        AUDIO,
        AVATAR,
        COVER,
    }
}
